﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ServiceStack.Redis;
using ServiceStack.Redis.Generic;

namespace Ruanmou.Framework.RedisHelper
{
    public  class RedisHeper:IDisposable
    {
        /// <summary>
        /// 定义redis客户端
        /// </summary>
        public  RedisClient redisClient = new RedisClient("127.0.0.1", 6379);


        //默认缓存过期时间单位秒
        public int secondsTimeOut = 30 * 60;

        /// <summary>
        /// 缓存池
        /// </summary>
        public PooledRedisClientManager prcm = new PooledRedisClientManager();

        /// <summary>
        /// 缓冲池
        /// </summary>
        /// <param name="readWriteHosts"></param>
        /// <param name="readOnlyHosts"></param>
        /// <returns></returns>
        public static PooledRedisClientManager CreatePool(string[] readWriteHosts, string[] readOnlyHosts)
        {
            return new PooledRedisClientManager(readWriteHosts, readOnlyHosts, new RedisClientManagerConfig {
                MaxWritePoolSize = readWriteHosts.Length*5,
                MaxReadPoolSize = readOnlyHosts.Length*5,
                AutoStart=true
            });
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="isPool"></param>
        public RedisHeper(bool isPool)
        {
            if (isPool)
            {
                prcm = CreatePool(new string[] { "127.0.0.1:6379" }, new string[] { "127.0.0.1:6379" });
                redisClient = prcm.GetClient() as RedisClient;
            }
        }
        #region string操作

        /// <summary>
        /// 设置值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="t"></param>
        /// <param name="time"></param>
        /// <returns></returns>
        public bool Set<T>(string key, T t, int timeout = 0)
        {
            if (timeout >= 0)
            {
                if (timeout > 0)
                {
                    return redisClient.Set<T>(key, t, DateTime.Now.AddSeconds(timeout));
                }
                return redisClient.Set<T>(key, t, DateTime.Now.AddSeconds(secondsTimeOut));
            }
            else
            {
                return redisClient.Set<T>(key, t);
            }
          
        }



        /// <summary>
        /// 获取值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public T Get<T>(string key)
        {
            return redisClient.Get<T>(key);
        }


        /// <summary>
        /// 移除
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool Remove(string key)
        {
            return redisClient.Remove(key);
        }


        /// <summary>
        /// 添加数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="t"></param>
        /// <param name="time"></param>
        /// <returns></returns>
        public bool Add<T>(string key, T t,int timeout = 0)
        {
            if (timeout >= 0)
            {
                if (timeout > 0)
                {
                    return redisClient.Add<T>(key, t, DateTime.Now.AddSeconds(timeout));
                }
                return redisClient.Add<T>(key, t, DateTime.Now.AddSeconds(secondsTimeOut));
            }
            else
            {
                return redisClient.Add<T>(key, t);
            }
        }

        #endregion



        #region 链表操作

        /// <summary>
        /// 根据IEnumerable数据添加链表
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="listId"></param>
        /// <param name="value"></param>
        /// <param name="time"></param>
        public void AddList<T>(string listId, IEnumerable<T> values, int timeout = 0)
        {
            IRedisTypedClient<T> typedClient = redisClient.As<T>();

            if (timeout >= 0)
            {
                if (timeout > 0)
                {
                    redisClient.Expire(listId, timeout);
                }
                redisClient.Expire(listId, secondsTimeOut);
            }
            typedClient.Lists[listId].AddRange(values);
            typedClient.Save();
        }

        /// <summary>
        /// 添加单个实体到链表中去
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="listId"></param>
        /// <param name="item"></param>
        /// <param name="timeout"></param>
        public void AddEntityToList<T>(string listId, T item, int timeout = 0)
        {
            IRedisTypedClient<T> typedClient = redisClient.As<T>();

            if (timeout >= 0)
            {
                if (timeout > 0)
                {
                    redisClient.Expire(listId, timeout);
                }
                redisClient.Expire(listId, secondsTimeOut);
            }
            typedClient.Lists[listId].Add(item);
            typedClient.Save();
        }


        /// <summary>
        /// 获取链表
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="listId"></param>
        /// <returns></returns>
        public IEnumerable<T> GetList<T>(string listId)
        {
            IRedisTypedClient<T> typedClient = redisClient.As<T>();
            return  typedClient.Lists[listId];
        }


        /// <summary>
        /// 从链表中删除单个实体
        /// </summary>
        /// <param name="listId"></param>
        public void RemoveEntityFromList<T>(string listId,T item)
        {
            IRedisTypedClient<T> typedClient = redisClient.As<T>();

            typedClient.Lists[listId].Remove(item);
            typedClient.Save();
        }


        /// <summary>
        /// 指定条件删除数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="listId"></param>
        /// <param name="func"></param>
        public void RemoveEntityFromList<T>(string listId, Func<T ,bool> func)
        {
                IRedisTypedClient<T> typedClient = redisClient.As<T>();
                var redisList = typedClient.Lists[listId];
                T value = redisList.Where(func).FirstOrDefault();
                redisList.RemoveValue(value);
                typedClient.Save();
        }


        #endregion

        #region IDisposable Support
        private bool disposedValue = false; // 要检测冗余调用

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    // TODO: 释放托管状态(托管对象)。
                }

                // TODO: 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。
                // TODO: 将大型字段设置为 null。

                disposedValue = true;
            }
        }

        // TODO: 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。
        // ~RedisHeper() {
        //   // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
        //   Dispose(false);
        // }

        // 添加此代码以正确实现可处置模式。
        void IDisposable.Dispose()
        {
            // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
            Dispose(true);
            // TODO: 如果在以上内容中替代了终结器，则取消注释以下行。
            // GC.SuppressFinalize(this);
        }
        #endregion

    }
}
